
#pragma once

#include "Runtime.Low/Pipeline.h"
#include "Node.h"

namespace ttg_internal
{
	namespace utils
	{
		///<summary>
		/// Wrapper for parameters of one sub-pipeline.
		///</summary>
		public ref class BasicPipeline
		{
			private:
				System::String ^_name;
				System::Collections::ObjectModel::ObservableCollection<Node ^> ^_nodes;
			internal:
				///<summary>
				/// Creates sub-pipeline with required values.
				///</summary>
				BasicPipeline(ttg::math::uint64 name,
							  std::vector<ttg_internal::pipeline::LiteNodeInfo> &nodes)
				{
					try
					{
						//Getting name.
						ParameterSet ^n = ParameterManager::getRef()->findSet(name);
						if (n == nullptr)
							throw gcnew System::ApplicationException("Cannot find corresponded parameter");
						_name = n->Name;
						//Creating nodes.
						_nodes = gcnew System::Collections::ObjectModel::ObservableCollection<Node ^>();
						System::Collections::Generic::Dictionary<ttg::math::uint64, Node ^> ^refs
							= gcnew System::Collections::Generic::Dictionary<ttg::math::uint64, Node ^>();
						for (size_t i = 0; i < nodes.size(); i++)
						{
							Node ^n = gcnew Node(&nodes[i]);
							_nodes->Add(n);
							refs->Add(nodes[i].getName(), n);
						}
						//Connecting nodes.
						for (size_t i = 0; i < nodes.size(); i++)
						{
							Node ^n = refs[nodes[i].getName()];
							for (size_t j = 0; j < nodes[i].getOutputs().size(); j++)
							{
								n->Outputs->Add(refs[nodes[i].getOutputs()[j]]);
							}
						}
					}
					catch (System::Exception ^ex)
					{
						throw gcnew System::ApplicationException("Cannot deserialize pipeline nodes", ex);
					}
				}
			public:
				///<summary>
				/// Returns name of the pipeline.
				///</summary>
				property System::String ^Name
				{
					System::String ^get()
					{ return _name; }
				}
				///<summary>
				/// Returns all nodes of the pipeline.
				///</summary>
				property System::Collections::ObjectModel::ObservableCollection<Node ^> ^Nodes
				{
					System::Collections::ObjectModel::ObservableCollection<Node ^> ^get()
					{ return _nodes; }
				}
		};
	}
}
